package com.team.file.service;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.team.common.core.utils.StringUtils;
import com.team.common.core.utils.file.FileUtils;
import com.team.file.utils.FileUploadUtils;

import java.io.InputStream;

/**
 * 本地文件存储
 * 
 * @author ruoyi
 */
@Primary
@Service
public class LocalSysFileServiceImpl implements ISysFileService
{
    /**
     * 资源映射路径 前缀
     */
    @Value("${file.prefix}")
    public String localFilePrefix;

    /**
     * 域名或本机访问地址
     */
    @Value("${file.domain}")
    public String domain;
    
    /**
     * 上传文件存储在本地的根路径
     */
    @Value("${file.path}")
    private String localFilePath;

    /**
     * OSS 访问的 Endpoint 地址
     * 从 application.properties 中读取配置项：oss.endpoint
     * 示例值：https://oss-cn-beijing.aliyuncs.com
     */
    @Value("${oss.endpoint}")
    private String endpoint;

    /**
     * OSS 访问的 Access Key ID
     * 从 application.properties 中读取配置项：oss.accessKeyId
     * 注意：为了安全，建议不要将 Access Key 直接写在配置文件中，
     * 而是通过环境变量传递（如 OSS_ACCESS_KEY_ID）
     * 如果配置文件中未设置，则需要通过其他方式（如 Environment）获取
     */
    @Value("${oss.accessKeyId}")
    private String accessKeyId;

    /**
     * OSS 访问的 Access Key Secret
     * 从 application.properties 中读取配置项：oss.accessKeySecret
     * 注意：为了安全，建议不要将 Access Key Secret 直接写在配置文件中，
     * 而是通过环境变量传递（如 OSS_ACCESS_KEY_SECRET）
     * 如果配置文件中未设置，则需要通过其他方式（如 Environment）获取
     */
    @Value("${oss.accessKeySecret}")
    private String accessKeySecret;

    /**
     * OSS Bucket 名称
     * 从 application.properties 中读取配置项：oss.bucketName
     * 示例值：lizs123
     */
    @Value("${oss.bucketName}")
    private String bucketName;

    /**
     * OSS Object 的完整路径（不包含 Bucket 名称）
     * 从 application.properties 中读取配置项：oss.objectName
     * 示例值：exampledir/exampleobject.txt
     */
    @Value("${oss.objectName}")
    private String objectName;

    /**
     * OSS Bucket 所在地域
     * 从 application.properties 中读取配置项：oss.region
     * 示例值：cn-beijing
     */
    @Value("${oss.region}")
    private String region;

    /**
     * 本地文件上传接口
     * 
     * @param file 上传的文件
     * @return 访问地址
     * @throws Exception
     */
    @Override
    public String uploadFile(MultipartFile file) throws Exception
    {
        String name = FileUploadUtils.upload(localFilePath, file);
        String url = domain + localFilePrefix + name;
        return url;
    }

    /**
     * 本地文件删除接口
     * 
     * @param fileUrl 文件访问URL
     * @throws Exception
     */
    @Override
    public void deleteFile(String fileUrl) throws Exception
    {
        String localFile = StringUtils.substringAfter(fileUrl, localFilePrefix);
        FileUtils.deleteFile(localFilePath + localFile);
    }

    /**
     * OSS文件上传接口
     *
     * @param file 上传的文件
     * @return 访问地址
     * {
     *     "code": 200,
     *     "msg": null,
     *     "data": {
     *         "name": "屏幕截图 2023-05-26 003236_20250709170341A001.png",
     *         "url": "https://lizs123.oss-cn-beijing.aliyuncs.com/2025/07/09/屏幕截图 2023-05-26 003236_20250709170341A001.png"
     *     }
     * }
     * @throws Exception
     */

    @Override
    public String uploadOSSFile(MultipartFile file) throws Exception {
        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时，调用shutdown方法以释放资源。
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // 修改唯一文件名
            String objectName = FileUploadUtils.extractFilename(file);

            InputStream inputStream = file.getInputStream();
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 设置该属性可以返回response。如果不设置，则返回的response为空。
            putObjectRequest.setProcess("true");
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            // 如果上传成功，则返回200。
            System.out.println(result.getResponse().getStatusCode());

            //文件访问路径
            // 返回文件的访问地址
            return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
            // 处理OSS异常
            throw new RuntimeException("OSS Exception: " + oe.getErrorMessage(), oe);
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
            // 处理客户端异常
            throw new RuntimeException("OSS Client Exception: " + ce.getMessage(), ce);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * OSS文件删除接口
     *
     * @param fileUrl 文件访问URL 如：https://lizs123.oss-cn-beijing.aliyuncs.com/2025/07/09/屏幕截图 2023-05-26 003236_20250709170341A001.png
     * @throws Exception
     */
    @Override
    public String deleteOSSFile(String fileUrl) throws Exception {

        // 1. 从完整URL中提取对象键（去掉域名部分）
        String objectKey = FileUploadUtils.extractObjectKeyFromUrl(fileUrl);

        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // 2. 检查文件是否存在（可选，调试用）
            if (!ossClient.doesObjectExist(bucketName, objectKey)) {
                throw new RuntimeException("File not found: " + fileUrl);
            }

            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(bucketName, fileUrl);
            // 返回删除成功的消息
            return "File deleted successfully: " + fileUrl;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
            throw new RuntimeException("OSS Exception: " + oe.getErrorMessage(), oe);
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
            throw new RuntimeException("OSS Client Exception: " + ce.getMessage(), ce);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
